﻿using EdiNet;
using Xunit;
using System;
using System.IO;
using System.Text;
using System.Xml;

namespace EdiNet.Test
{

    public class EdiXmlReaderTest : IDisposable 
    {
        public const string ResourceBasePath = "EdiXmlReaderTest";

        private EdiXmlReader reader;
        private Stream ediStream;

        public EdiXmlReaderTest()
        {
            ediStream = StreamHelper.GetResourceStream(ResourceBasePath, "T.txt");
            reader = new EdiXmlReader(ediStream);
        }

        public void Dispose()
        {
            reader.Close();
        }


        /// <summary>
        ///A test for EdiXmlReader Constructor
        ///</summary>
        [Fact()]
        public void EdiXmlReaderConstructorTest()
        {
            EdiStreamReader ediStream = new EdiStreamReader(new MemoryStream());
            EdiXmlReader target = new EdiXmlReader(ediStream);
        }

        /// <summary>
        ///A test for EdiXmlReader Constructor
        ///</summary>
        [Fact()]
        public void EdiXmlReaderConstructorTest1()
        {
            Stream ediStream = new MemoryStream();
            Encoding enc = DefaultEdiEncoding.Encoding;
            EdiXmlReader target = new EdiXmlReader(ediStream, enc);
        }

        /// <summary>
        ///A test for EdiXmlReader Constructor
        ///</summary>
        [Fact()]
        public void EdiXmlReaderConstructorTest2()
        {
            Stream ediStream = new MemoryStream();
            EdiXmlReader target = new EdiXmlReader(ediStream);
        }

        /// <summary>
        ///A test for Close
        ///</summary>
        [Fact()]
        public void CloseTest()
        {
            reader.Close();
            Assert.Throws<ObjectDisposedException>(delegate()
            {
                ediStream.ReadByte(); //ObjectDisposedException
            });
        }

        /// <summary>
        ///A test for GetAttribute
        ///</summary>
        [Fact()]
        public void GetAttributeTest()
        {
            Assert.Null(reader.GetAttribute("AAA"));
        }

        /// <summary>
        ///A test for GetAttribute
        ///</summary>
        [Fact()]
        public void GetAttributeTest1()
        {
            Assert.Null(reader.GetAttribute("AAA", "BBB"));
        }

        /// <summary>
        ///A test for GetAttribute
        ///</summary>
        [Fact()]
        public void GetAttributeTest2()
        {
            Assert.Throws<ArgumentOutOfRangeException>(delegate()
            {
                reader.GetAttribute(0);  //ArgumentOutOfRangeException
            });
        }

        /// <summary>
        ///A test for LookupNamespace
        ///</summary>
        [Fact()]
        public void LookupNamespaceTest()
        {
            Assert.Null(reader.LookupNamespace("AAA"));
        }

        /// <summary>
        ///A test for MoveToAttribute
        ///</summary>
        [Fact()]
        public void MoveToAttributeTest()
        {
            Assert.False(reader.MoveToAttribute("AAA"));
        }

        /// <summary>
        ///A test for MoveToAttribute
        ///</summary>
        [Fact()]
        public void MoveToAttributeTest1()
        {
            Assert.False(reader.MoveToAttribute("AAA", "BB"));
        }

        /// <summary>
        ///A test for MoveToElement
        ///</summary>
        [Fact()]
        public void MoveToElementTest()
        {
            Assert.False(reader.MoveToElement());
        }

        /// <summary>
        ///A test for MoveToFirstAttribute
        ///</summary>
        [Fact()]
        public void MoveToFirstAttributeTest()
        {
            Assert.False(reader.MoveToFirstAttribute());
        }

        /// <summary>
        ///A test for MoveToNextAttribute
        ///</summary>
        [Fact()]
        public void MoveToNextAttributeTest()
        {
            Assert.False(reader.MoveToNextAttribute());
        }

        /// <summary>
        ///A test for Read
        ///</summary>
        [Fact()]
        public void ReadTest()
        {
            Assert.True(reader.Read());
        }

        /// <summary>
        ///A test for ReadAttributeValue
        ///</summary>
        [Fact()]
        public void ReadAttributeValueTest()
        {
            Assert.False(reader.ReadAttributeValue());
        }

        /// <summary>
        ///A test for ResolveEntity
        ///</summary>
        [Fact()]
        public void ResolveEntityTest()
        {
            Assert.Throws<InvalidOperationException>(delegate()
            {
                reader.ResolveEntity(); //InvalidOperationException
            });
        }

        /// <summary>
        ///A test for AttributeCount
        ///</summary>
        [Fact()]
        public void AttributeCountTest()
        {
            Assert.Equal(0, reader.AttributeCount);
        }

        /// <summary>
        ///A test for BaseURI
        ///</summary>
        [Fact()]
        public void BaseURITest()
        {
            Assert.Equal(string.Empty, reader.BaseURI);
        }

        /// <summary>
        ///A test for Depth
        ///</summary>
        [Fact()]
        public void DepthTest()
        {
            Assert.Equal(0, reader.Depth);
            reader.Read();
            Assert.Equal(0, reader.Depth);
            reader.Read();
            Assert.Equal(1, reader.Depth);
        }

        /// <summary>
        ///A test for EOF
        ///</summary>
        [Fact()]
        public void EOFTest()
        {
            while (reader.Read())
                ;
            Assert.True(reader.EOF);
        }

        /// <summary>
        ///A test for IsEmptyElement
        ///</summary>
        [Fact()]
        public void IsEmptyElementTest()
        {
            //no empty elements
            Assert.False(reader.IsEmptyElement);
            reader.Read();//EdiXml
            Assert.False(reader.IsEmptyElement);
            reader.Read();//ISA 
            Assert.False(reader.IsEmptyElement);
            reader.Read();//ISA01
            Assert.False(reader.IsEmptyElement);
            reader.Read();//ISA02
            Assert.False(reader.IsEmptyElement);

        }

        /// <summary>
        ///A test for LocalName
        ///</summary>
        [Fact()]
        public void LocalNameTest()
        {
            Assert.Equal(string.Empty, reader.LocalName);
            reader.Read();
            Assert.Equal("EdiXml", reader.LocalName);
            reader.Read();
            Assert.Equal("ISA", reader.LocalName);
            reader.Read();
            Assert.Equal("E1", reader.LocalName);
            reader.Read();
            Assert.Equal(string.Empty, reader.LocalName);
        }

        /// <summary>
        ///A test for NameTable
        ///</summary>
        [Fact()]
        public void NameTableTest()
        {
            reader.ReadStartElement("EdiXml");
            reader.ReadStartElement("ISA");
            object e1 = reader.LocalName; //E1
            reader.ReadElementString("E1");

            reader.ReadToNextSibling("DOESNOTEXIST");
            reader.ReadEndElement();
            reader.ReadStartElement("GS");
            object e2 = reader.LocalName;
            reader.ReadStartElement("E1");

            Assert.True(e1 == e2); //compare object references
        }

        /// <summary>
        ///A test for NamespaceURI
        ///</summary>
        [Fact()]
        public void NamespaceURITest()
        {
            Assert.Equal(string.Empty, reader.NamespaceURI);
        }

        /// <summary>
        ///A test for NodeType
        ///</summary>
        [Fact()]
        public void NodeTypeTest()
        {
            Assert.Equal(XmlNodeType.None, reader.NodeType);
            reader.Read();
            Assert.Equal(XmlNodeType.Element, reader.NodeType);
            reader.Read();
            Assert.Equal(XmlNodeType.Element, reader.NodeType);
            reader.Read();
            Assert.Equal(XmlNodeType.Element, reader.NodeType);
            reader.Read();
            Assert.Equal(XmlNodeType.Text, reader.NodeType);
            reader.Read();
            Assert.Equal(XmlNodeType.EndElement, reader.NodeType);
        }

        /// <summary>
        ///A test for Prefix
        ///</summary>
        [Fact()]
        public void PrefixTest()
        {
            Assert.Equal(string.Empty, reader.Prefix);
        }

        /// <summary>
        ///A test for ReadState
        ///</summary>
        [Fact()]
        public void ReadStateTest()
        {
            Assert.Equal(ReadState.Initial, reader.ReadState);
            reader.Read();
            Assert.Equal(ReadState.Interactive, reader.ReadState);
            while (reader.Read())
                ;
            Assert.Equal(ReadState.EndOfFile, reader.ReadState);
            reader.Close();
            Assert.Equal(ReadState.Closed, reader.ReadState);
        }

        /// <summary>
        ///A test for Value
        ///</summary>
        [Fact()]
        public void ValueTest()
        {
            Assert.Equal(string.Empty, reader.Value);
            reader.Read(); //EdiXml
            Assert.Equal(string.Empty, reader.Value);
            reader.Read(); //ISA
            Assert.Equal(string.Empty, reader.Value);
            reader.Read(); //E1
            Assert.Equal(string.Empty, reader.Value);
            reader.Read(); //Text
            Assert.Equal("00", reader.Value);
            reader.Read(); //End Element
            Assert.Equal(string.Empty, reader.Value);
        }
        [Fact()]
        public void ReadCompositeTest()
        {
            reader.Read();//edixml
            reader.Read();//isa
            reader.ReadToFollowing("IT1");
            reader.Read();//E1
            Assert.True(reader.ReadToFollowing("C3"));
            reader.ReadStartElement("C3");
            reader.ReadStartElement("E1");
            Assert.Equal("CA", reader.ReadString());
            reader.ReadEndElement();
            reader.ReadStartElement("E2");
            Assert.Equal("25", reader.ReadString());
            reader.ReadEndElement();
            reader.ReadEndElement();
            reader.ReadStartElement("E4");

        }

        [Fact()]
        public void ReaderBehaviourTest()
        {
            XmlReaderSettings s = new XmlReaderSettings();
            s.IgnoreWhitespace = false;
            XmlReader xmlReader = XmlReader.Create(StreamHelper.GetResourceStream(ResourceBasePath, "T.xml"), s);

            while (xmlReader.Read())
            {
                Assert.True(reader.Read());

                Assert.Equal(xmlReader.NodeType, reader.NodeType);
                Assert.Equal(xmlReader.Value, reader.Value);
                Assert.Equal(xmlReader.LocalName, reader.LocalName);
                Assert.Equal(xmlReader.Depth, reader.Depth);
                Assert.Equal(xmlReader.ReadState, reader.ReadState);
            }

            Assert.True(reader.Read());

            Assert.Equal(xmlReader.NodeType, reader.NodeType);
            Assert.Equal(xmlReader.Value, reader.Value);
            Assert.Equal(xmlReader.LocalName, reader.LocalName);
            Assert.Equal(xmlReader.Depth, reader.Depth);
            Assert.Equal(xmlReader.ReadState, reader.ReadState);

            Assert.False(reader.Read());

        }
    }
}
